﻿///////////////////////////////////////////////////////////////////////////////
//
//  This file is part of MathLib.NET.
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2.1 of the License, or (at your option) any later version.
//  
//  This library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//  Lesser General Public License for more details.
//  
//  You should have received a copy of the GNU Lesser General Public
//  License along with this library;  If not, see 
//  <http://www.gnu.org/licenses/>.
//
///////////////////////////////////////////////////////////////////////////////

using MathLib;
using ILNumerics;
using NUnit.Framework;

namespace MathLibTest
{
    [TestFixture]
    public class polysumTest
    {
        [Test]
        public void d_test1()
        {
            double[] u = new double[] { 1, 2, 3 };
            double[] v = new double[] { 2, 3, 4 };
            double[] answer = new double[] { 3, 5, 7 };

            double[] test_res = MLMath.polysum(u, v);

            Assert.IsTrue(TestUtils.ArrayEqual(test_res, answer));
        }

        [Test]
        public void d_test2()
        {
            double[] u = new double[] { 1, 2, 3 };
            double[] v = new double[] { 2, 3 };
            double[] answer = new double[] { 1, 4, 6 };

            double[] test_res = MLMath.polysum(u, v);

            Assert.IsTrue(TestUtils.ArrayEqual(test_res, answer));
        }

        [Test]
        public void d_test3()
        {
            double[] u = new double[] { 1, 2 };
            double[] v = new double[] { 2, 3, 4 };
            double[] answer = new double[] { 2, 4, 6 };

            double[] test_res = MLMath.polysum(u, v);

            Assert.IsTrue(TestUtils.ArrayEqual(test_res, answer));
        }

        [Test]
        public void d_test4()
        {
            double[] u = new double[] { -2, -3, -4 };
            double[] v = new double[] { 2, 3, 4 };
            double[] answer = new double[] { 0 };

            double[] test_res = MLMath.polysum(u, v);

            Assert.IsTrue(TestUtils.ArrayEqual(test_res, answer));
        }

        [Test]
        public void d_test5()
        {
            double[] u = new double[] { -2, 2, 3 };
            double[] v = new double[] { 2, 3, 4 };
            double[] answer = new double[] { 5, 7 };

            double[] test_res = MLMath.polysum(u, v);

            Assert.IsTrue(TestUtils.ArrayEqual(test_res, answer));
        }

        [Test]
        public void c_test1()
        {
            complex[] u = new complex[] { new complex(1, 0), new complex(2, 0), new complex(3, 0) };
            complex[] v = new complex[] { new complex(2, 0), new complex(3, 0), new complex(4, 0) };
            complex[] answer = new complex[] { new complex(3, 0), new complex(5, 0), new complex(7, 0) };

            complex[] test_res = MLMath.polysum(u, v);

            Assert.IsTrue(TestUtils.ArrayEqual(test_res, answer));
        }

        [Test]
        public void c_test2()
        {
            complex[] u = new complex[] { new complex(1, 0), new complex(2, 0), new complex(3, 0) };
            complex[] v = new complex[] { new complex(2, 0), new complex(3, 0) };
            complex[] answer = new complex[] { new complex(1, 0), new complex(4, 0), new complex(6, 0) };

            complex[] test_res = MLMath.polysum(u, v);

            Assert.IsTrue(TestUtils.ArrayEqual(test_res, answer));
        }

        [Test]
        public void c_test3()
        {
            complex[] u = new complex[] { new complex(1, 0), new complex(2, 0) };
            complex[] v = new complex[] { new complex(2, 0), new complex(3, 0), new complex(4, 0) };
            complex[] answer = new complex[] { new complex(2, 0), new complex(4, 0), new complex(6, 0) };

            complex[] test_res = MLMath.polysum(u, v);

            Assert.IsTrue(TestUtils.ArrayEqual(test_res, answer));
        }

        [Test]
        public void c_test4()
        {
            complex[] u = new complex[] { -new complex(2, 0), -new complex(3, 0), -new complex(4, 0) };
            complex[] v = new complex[] { new complex(2, 0), new complex(3, 0), new complex(4, 0) };
            complex[] answer = new complex[] { new complex(0, 0) };

            complex[] test_res = MLMath.polysum(u, v);

            Assert.IsTrue(TestUtils.ArrayEqual(test_res, answer));
        }

        [Test]
        public void c_test5()
        {
            complex[] u = new complex[] { -new complex(2, 0), new complex(2, 0), new complex(3, 0) };
            complex[] v = new complex[] { new complex(2, 0), new complex(3, 0), new complex(4, 0) };
            complex[] answer = new complex[] { new complex(5, 0), new complex(7, 0) };

            complex[] test_res = MLMath.polysum(u, v);

            Assert.IsTrue(TestUtils.ArrayEqual(test_res, answer));
        }
    }

    [TestFixture]
    public class polydifTest
    {
        [Test]
        public void d_test1()
        {
            double[] u = new double[] { 1, 2, 3 };
            double[] v = new double[] { -2, -3, -4 };
            double[] answer = new double[] { 3, 5, 7 };

            double[] test_res = MLMath.polydif(u, v);

            Assert.IsTrue(TestUtils.ArrayEqual(test_res, answer));
        }

        [Test]
        public void d_test2()
        {
            double[] u = new double[] { 1, 2, 3 };
            double[] v = new double[] { -2, -3 };
            double[] answer = new double[] { 1, 4, 6 };

            double[] test_res = MLMath.polydif(u, v);

            Assert.IsTrue(TestUtils.ArrayEqual(test_res, answer));
        }

        [Test]
        public void d_test3()
        {
            double[] u = new double[] { 1, 2 };
            double[] v = new double[] { -2, -3, -4 };
            double[] answer = new double[] { 2, 4, 6 };

            double[] test_res = MLMath.polydif(u, v);

            Assert.IsTrue(TestUtils.ArrayEqual(test_res, answer));
        }

        [Test]
        public void d_test4()
        {
            double[] u = new double[] { -2, -3, -4 };
            double[] v = new double[] { -2, -3, -4 };
            double[] answer = new double[] { 0 };

            double[] test_res = MLMath.polydif(u, v);

            Assert.IsTrue(TestUtils.ArrayEqual(test_res, answer));
        }

        [Test]
        public void d_test5()
        {
            double[] u = new double[] { -2, 2, 3 };
            double[] v = new double[] { -2, -3, -4 };
            double[] answer = new double[] { 5, 7 };

            double[] test_res = MLMath.polydif(u, v);

            Assert.IsTrue(TestUtils.ArrayEqual(test_res, answer));
        }

        [Test]
        public void c_test1()
        {
            complex[] u = new complex[] { new complex(1, 0), new complex(2, 0), new complex(3, 0) };
            complex[] v = new complex[] { new complex(-2, 0), new complex(-3, 0), new complex(-4, 0) };
            complex[] answer = new complex[] { new complex(3, 0), new complex(5, 0), new complex(7, 0) };

            complex[] test_res = MLMath.polydif(u, v);

            Assert.IsTrue(TestUtils.ArrayEqual(test_res, answer));
        }

        [Test]
        public void c_test2()
        {
            complex[] u = new complex[] { new complex(1, 0), new complex(2, 0), new complex(3, 0) };
            complex[] v = new complex[] { new complex(-2, 0), new complex(-3, 0) };
            complex[] answer = new complex[] { new complex(1, 0), new complex(4, 0), new complex(6, 0) };

            complex[] test_res = MLMath.polydif(u, v);

            Assert.IsTrue(TestUtils.ArrayEqual(test_res, answer));
        }

        [Test]
        public void c_test3()
        {
            complex[] u = new complex[] { new complex(1, 0), new complex(2, 0) };
            complex[] v = new complex[] { new complex(-2, 0), new complex(-3, 0), new complex(-4, 0) };
            complex[] answer = new complex[] { new complex(2, 0), new complex(4, 0), new complex(6, 0) };

            complex[] test_res = MLMath.polydif(u, v);

            Assert.IsTrue(TestUtils.ArrayEqual(test_res, answer));
        }

        [Test]
        public void c_test4()
        {
            complex[] u = new complex[] { -new complex(2, 0), -new complex(3, 0), -new complex(4, 0) };
            complex[] v = new complex[] { new complex(-2, 0), new complex(-3, 0), new complex(-4, 0) };
            complex[] answer = new complex[] { new complex(0, 0) };

            complex[] test_res = MLMath.polydif(u, v);

            Assert.IsTrue(TestUtils.ArrayEqual(test_res, answer));
        }

        [Test]
        public void c_test5()
        {
            complex[] u = new complex[] { new complex(-2, 0), new complex(2, 0), new complex(3, 0) };
            complex[] v = new complex[] { new complex(-2, 0), new complex(-3, 0), new complex(-4, 0) };
            complex[] answer = new complex[] { new complex(5, 0), new complex(7, 0) };

            complex[] test_res = MLMath.polydif(u, v);

            Assert.IsTrue(TestUtils.ArrayEqual(test_res, answer));
        }
    }

    [TestFixture]
    public class convTest
    {
        [Test]
        public void d_test1()
        {
            double[] u = new double[] { 1, 2, 3 };
            double[] v = new double[] { 1, 2, 3 };
            double[] answer = new double[] { 1, 4, 6+4, 12, 9 };

            double[] test_res = MLMath.conv(u, v);

            Assert.IsTrue(TestUtils.ArrayEqual(test_res, answer));
        }

        [Test]
        public void d_test2()
        {
            double[] u = new double[] { 1, 2, 3, 5 };
            double[] v = new double[] { 2 };
            double[] answer = new double[] { 2, 4, 6, 10 };

            double[] test_res = MLMath.conv(u, v);

            Assert.IsTrue(TestUtils.ArrayEqual(test_res, answer));
        }

        [Test]
        public void d_test2r()
        {
            double[] u = new double[] { 2 };
            double[] v = new double[] { 1, 2, 3, 5 };
            double[] answer = new double[] { 2, 4, 6, 10 };

            double[] test_res = MLMath.conv(u, v);

            Assert.IsTrue(TestUtils.ArrayEqual(test_res, answer));
        }

        [Test]
        public void c_test1()
        {
            complex[] u = new complex[] { new complex(1, 0), new complex(2, 0), new complex(3, 0) };
            complex[] v = new complex[] { new complex(1, 0), new complex(2, 0), new complex(3, 0) };
            complex[] answer = new complex[] { new complex(1, 0), new complex(4, 0), new complex(6 + 4, 0), new complex(12, 0), new complex(9, 0) };

            complex[] test_res = MLMath.conv(u, v);

            Assert.IsTrue(TestUtils.ArrayEqual(test_res, answer));
        }

        [Test]
        public void c_test2()
        {
            complex[] u = new complex[] { new complex(1, 0), new complex(2, 0), new complex(3, 0), new complex(5, 0) };
            complex[] v = new complex[] { new complex(2, 0) };
            complex[] answer = new complex[] { new complex(2, 0), new complex(4, 0), new complex(6, 0), new complex(10, 0) };

            complex[] test_res = MLMath.conv(u, v);

            Assert.IsTrue(TestUtils.ArrayEqual(test_res, answer));
        }

        [Test]
        public void c_test2r()
        {
            complex[] u = new complex[] { new complex(2, 0) };
            complex[] v = new complex[] { new complex(1, 0), new complex(2, 0), new complex(3, 0), new complex(5, 0) };
            complex[] answer = new complex[] { new complex(2, 0), new complex(4, 0), new complex(6, 0), new complex(10, 0) };

            complex[] test_res = MLMath.conv(u, v);

            Assert.IsTrue(TestUtils.ArrayEqual(test_res, answer));
        }
    }

    [TestFixture]
    public class polyintTest
    {
        [Test]
        public void d_test1_with_C()
        {
            double[] input = new double[] { 1, 2, 3, 4.5 };
            double C = 10.999;
            double[] answer = new double[] { 1.0000000001/4, 2.0/3, 3.0/2, 4.5, C };

            double[] test_res = MLMath.polyint(input, C);

            Assert.IsTrue(TestUtils.ArrayEqual(test_res, answer));
        }

        [Test]
        public void c_test1_with_C()
        {
            complex[] input = new complex[] { new complex(1, 2), new complex(3, 4), new complex(5, 6), new complex(7, 8) };
            complex C = new complex(1.1234, 2.1243);
            complex[] answer = new complex[] { new complex(1, 2)/4, new complex(3, 4)/3, new complex(5, 6)/2, new complex(7, 8), C };

            complex[] test_res = MLMath.polyint(input, C);

            Assert.IsTrue(TestUtils.ArrayEqual(test_res, answer));
        }

        [Test]
        public void d_test1_no_C()
        {
            double[] input = new double[] { 1, 2, 3, 4.5 };
            double C = 0.0;
            double[] answer = new double[] { 1.0000000001 / 4, 2.0 / 3, 3.0 / 2, 4.5, C };

            double[] test_res = MLMath.polyint(input);

            Assert.IsTrue(TestUtils.ArrayEqual(test_res, answer));
        }

        [Test]
        public void c_test1_no_C()
        {
            complex[] input = new complex[] { new complex(1, 2), new complex(3, 4), new complex(5, 6), new complex(7, 8) };
            complex C = new complex(0.0, 0.0);
            complex[] answer = new complex[] { new complex(1, 2) / 4, new complex(3, 4) / 3, new complex(5, 6) / 2, new complex(7, 8), C };

            complex[] test_res = MLMath.polyint(input);

            Assert.IsTrue(TestUtils.ArrayEqual(test_res, answer));
        }
    }

    public class polyderTest
    {
        [Test]
        public void d_test1()
        {
            double[] input = new double[] { 1, 2, 3, 4.5 };
            double[] answer = new double[] { 1.0000000001 * 3, 2.0 * 2, 3.0 };

            double[] test_res = MLMath.polyder(input);

            Assert.IsTrue(TestUtils.ArrayEqual(test_res, answer));
        }

        [Test]
        public void d_mul()
        {
            double[] u = new double[] { 1, 2, 3, 5 };
            double[] v = new double[] { 1, 2, 3 };
            double[] answer = new double[] { 5, 16, 30, 34, 19 };

            double[] test_res = MLMath.polyder(u,v);

            Assert.IsTrue(TestUtils.ArrayEqual(test_res, answer));
        }

        [Test]
        public void d_frac()
        {
            double[] u = new double[] { 1, 2, 3, 5 };
            double[] v = new double[] { 1, 2, 3 };
            double[] num = new double[] { 1, 4, 10, 2, -1 };
            double[] den = new double[] { 1, 4, 10, 12, 9 };

            double[] test_num;
            double[] test_den;

            MLMath.polyder(u, v, out test_num, out test_den);

            Assert.IsTrue(TestUtils.ArrayEqual(test_num, num));
            Assert.IsTrue(TestUtils.ArrayEqual(test_den, den));
        }

        [Test]
        public void c_test1()
        {
            complex[] input = new complex[] { new complex(1, 2), new complex(3, 4), new complex(5, 6), new complex(7, 8) };
            complex[] answer = new complex[] { new complex(1, 2) * 3, new complex(3, 4) * 2, new complex(5, 6) };

            complex[] test_res = MLMath.polyder(input);

            Assert.IsTrue(TestUtils.ArrayEqual(test_res, answer));
        }

        [Test]
        public void c_mul()
        {
            complex[] u = new complex[] { new complex(1, 0), new complex(2, 0), new complex(3, 0), new complex(5, 0) };
            complex[] v = new complex[] { new complex(1, 0), new complex(2, 0), new complex(3, 0) };
            complex[] answer = new complex[] { new complex(5, 0), new complex(16, 0), new complex(30, 0), new complex(34, 0), new complex(19, 0) };

            complex[] test_res = MLMath.polyder(u, v);

            Assert.IsTrue(TestUtils.ArrayEqual(test_res, answer));
        }

        [Test]
        public void c_frac()
        {
            complex[] u = new complex[] { new complex(1, 0), new complex(2, 0), new complex(3, 0), new complex(5, 0) };
            complex[] v = new complex[] { new complex(1, 0), new complex(2, 0), new complex(3, 0) };
            complex[] num = new complex[] { new complex(1, 0), new complex(4, 0), new complex(10, 0), new complex(2, 0), -new complex(1, 0) };
            complex[] den = new complex[] { new complex(1, 0), new complex(4, 0), new complex(10, 0), new complex(12, 0), new complex(9, 0) };

            complex[] test_num;
            complex[] test_den;

            MLMath.polyder(u, v, out test_num, out test_den);

            Assert.IsTrue(TestUtils.ArrayEqual(test_num, num));
            Assert.IsTrue(TestUtils.ArrayEqual(test_den, den));
        }
    }
}
